package com.bj58.heatmap.db;

import java.io.FileInputStream;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.apache.log4j.Logger;

/**
 * dbcp数据库连接池的实现类(获取源数据库连接池)
 * @author zhaoxiang
 */
public class DBConnectionPool
{
	private static Logger log = Logger.getLogger(DBConnectionPool.class);
	private static ConcurrentHashMap<DBConfig, DataSource> dataSourceCache = new ConcurrentHashMap<DBConfig, DataSource>();
	private static HashMap<Integer, DBConfig> dbConfMap = new HashMap<Integer, DBConfig>();
 
	static{
    	for(DBConfig dbConfig : DBConfig.values()){
    		dbConfMap.put(dbConfig.getIntType(), dbConfig);
    	}
    }

    /**
     * 获得数据库连接
     * @param dbType
     * @return null if dbConfig is null else a free Connection.
     */
	public static Connection getConnection(int  dbType) 
	{
		try
		{
			DBConfig dbConfig = dbConfMap.get(dbType);
			if(dbConfig == null)
				return null;
			return getConnection(dbConfig);
		}catch (Exception e){
			log.error("error occurs when get a connection from DataSource:",e);
			return null;
		}
	}
	
    /**
     * 获得数据库连接
     * @param dbConfig
     * @return null if dbConfig is null else a free Connection.
     */
	public static Connection getConnection(DBConfig dbConfig) 
	{
		DataSource dataSource = null;
		try
		{
			dataSource = dataSourceCache.get(dbConfig);
			if(dataSource == null){
				synchronized(dataSourceCache){
					dataSource = dataSourceCache.get(dbConfig);
					if(dataSource == null){
						dataSource = createDataSource(dbConfig);
						if(dataSource != null){
							dataSourceCache.put(dbConfig, dataSource);
						}
					}
				}
			}
			
			return dataSource.getConnection();
		}catch (Exception e) {
			log.error("error occurs when get a connection from DataSource:",e);
			return null;
		}
		
	}

	/**
	 * 创建一个新的数据库连接池
	 * @return 新的数据库连接池，null表示创建失败
	 */
	private static DataSource createDataSource(DBConfig dbConfig)
	{
		if(dbConfig == null){
			return null;
		}
		DataSource dataSource = null;
		try
		{
			String path = dbConfig.getConfigPath();
			Properties p = new Properties();
			FileInputStream fis = new FileInputStream(path);
			p.load(fis);
			fis.close();
			
			//DBCP连接池的自我检测
			p.setProperty("validationQuery", "select 1");
			p.setProperty("testWhileIdle", "true");
			p.setProperty("testOnBorrow", "false");
			p.setProperty("testOnReturn", "true");
			p.setProperty("timeBetweenEvictionRunsMillis", "30000");
			p.setProperty("minEvictableIdleTimeMillis", "1800000");
			p.setProperty("numTestsPerEvictionRun", "3");
			p.setProperty("removeAbandoned", "true");
			p.setProperty("removeAbandonedTimeout", "60");
			
			dataSource = BasicDataSourceFactory.createDataSource(p);
		}catch (Exception e){
			e.printStackTrace();
		}
		
		return dataSource;
	}
	
}
